import json
import time
from fastapi import APIRouter, HTTPException, status, Query, Request, Depends
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field, validator
from typing import Dict, Any, Optional, AsyncGenerator
from agents.maxkb_agent import MaxKBAgent, maxkb_chat, get_maxkb_agent, maxkb_chat_stream
from core.config import settings
from services.chat_service import ChatService
from pydantic import BaseModel
from typing import List, Optional, Dict, Any, AsyncGenerator
from core.auto import get_current_user
import httpx

# 初始化MaxKB代理
maxkb_agent = MaxKBAgent()
# 初始化ChatService用于聊天记录管理
chat_service = ChatService()

# 聊天历史记录请求模型
class ChatHistoryRequest(BaseModel):
    # account_no is not used from request body, it's taken from authenticated user
    limit: Optional[int] = 50  
    offset: Optional[int] = 0   
    chat_id: Optional[str] = ""  


class ChatHistoryItem(BaseModel):
    role: str       # 角色（user/assistant）
    content: str    # 消息内容
    timestamp: str  # 时间戳
    chat_id: str    # 对话ID

# 请求模型定义 - 根据新的API规范更新
class MaxKBChatRequest(BaseModel):
    message: str = Field(..., description="用户查询内容", min_length=1, max_length=2000)
    chat_id: Optional[str] = Field(None, description="对话ID，默认使用配置中的MAXKB_Chat_ID")
    re_chat: Optional[bool] = Field(False, description="是否重新开始对话")
    
    @validator('message')
    def validate_query_not_empty(cls, v):
        if not v or not v.strip():
            raise ValueError('查询内容不能为空')
        return v.strip()

class MaxKBStreamRequest(BaseModel):
    message: str = Field(..., description="用户查询内容", min_length=1, max_length=2000)
    chat_id: Optional[str] = Field(None, description="对话ID，默认使用配置中的MAXKB_Chat_ID")
    re_chat: Optional[bool] = Field(False, description="是否重新开始对话")
    
    @validator('message')
    def validate_query_not_empty(cls, v):
        if not v or not v.strip():
            raise ValueError('查询内容不能为空')
        return v.strip()

# 响应模型定义 - 更新为包含chat_id
class MaxKBResponse(BaseModel):
    answer: Optional[str] = None
    chat_id: Optional[str] = None
    error: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None
    status: Optional[str] = None

# 创建路由对象
router = APIRouter(
    prefix="/api/maxkb",
    tags=["MaxKB知识库"],
)

# 非流式接口
@router.post("/chat")
async def maxkb_chat_handler(
    request: MaxKBChatRequest,
    current_user: Dict[str, Any] = Depends(get_current_user)
) -> Dict[str, Any]:
    """
    MaxKB知识库对话接口（非流式）
    使用配置中的MAXKB_Chat_ID或传入的chat_id
    """
    try:
        # 获取对话ID - 优先使用传入的chat_id，否则使用配置中的MAXKB_Chat_ID
        chat_id = request.chat_id or settings.MAXKB_Chat_ID
        if not chat_id:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="MaxKB对话ID未配置"
            )
        
        # 验证MaxKB配置
        agent = get_maxkb_agent()
        if not agent.api_url or not agent.api_key:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="MaxKB服务配置不完整"
            )
        
        # 获取account_no
        account_no = current_user.get("accountNo", "")
        
        
        # 使用更新后的API调用方式，传入account_no
        response = await maxkb_agent.send_message(
            message=request.message,
            chat_id=chat_id,
            re_chat=request.re_chat,
            account_no=account_no
        )
        
        # 处理错误
        if isinstance(response, dict) and "error" in response:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=response["error"]
            )
        
       
        if isinstance(response, dict):
            if "chat_id" not in response:
                response["chat_id"] = chat_id
            response["account_no"] = account_no
        
        
        if isinstance(response, dict) and "answer" in response:
            save_ok = await chat_service.save_chat_message(
                account_no=account_no,
                user_msg=request.message,
                assistant_msg=response["answer"]
            )
            if not save_ok:
                pass
            else:
                # 异步生成对话摘要
                import asyncio
                asyncio.create_task(chat_service.generate_summary(account_no=account_no))
        
        return response
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"服务异常: {str(e)}"
        )

# 流式输出接口
@router.post("/chat/stream", response_class=StreamingResponse)
async def maxkb_chat_stream_handler(
    request: MaxKBStreamRequest,
    current_user: Dict[str, Any] = Depends(get_current_user)
) -> StreamingResponse:
    """
    MaxKB知识库对话接口（流式）- 使用OpenAI兼容的API格式
    确保与前端createAIChatStream函数格式完全匹配
    
    Args:
        request: 请求数据，包含用户查询和可选的chat_id
        
    Returns:
        SSE格式的流式响应
    """
    try:
        # 获取account_no，确保与其他接口使用完全一致的用户标识
        account_no = current_user.get("accountNo", "")
        # 添加日志以验证account_no的值

        
        # 获取对话ID
        chat_id = request.chat_id or settings.MAXKB_Chat_ID
        if not chat_id:
            async def chat_id_error_generator():
                error_data = json.dumps({"error": "MaxKB对话ID未配置", "status": "error", "account_no": account_no})
                yield f"data: {error_data}\n\n"
            return StreamingResponse(
                chat_id_error_generator(),
                media_type="text/event-stream",
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        

        
        # 创建变量来累积流式响应的完整内容
        accumulated_response = ""
        start_time = time.time()
        
        # 定义流式生成器函数，优化实现以匹配前端createAIChatStream
        async def stream_generator() -> AsyncGenerator[str, None]:
            nonlocal accumulated_response
            save_ok = False  # 初始化save_ok避免未定义错误
            try:
                # 构建MaxKB流式接口URL
                base_url = settings.MAXKB_BASE_URL
                url = f"{base_url}/chat/completions"  # 使用OpenAI兼容格式
                
                
                headers = {
                    "Content-Type": "application/json",
                    "Authorization": f"Bearer {settings.MAXKB_API_KEY}"
                }
                
                
                payload = {
                    "model": "gpt-3.5-turbo",  # 固定模型名称
                    "messages": [
                        {
                            "role": "user",
                            "content": request.message
                        }
                    ],
                    "stream": True
                }
                
                # 使用httpx发送流式请求
                async with httpx.AsyncClient(timeout=None) as client:
                    async with client.stream('POST', url, json=payload, headers=headers) as response:
                        response.raise_for_status()
                        
                        # 逐块处理响应
                        async for chunk in response.aiter_bytes():
                            if chunk:
                                # 解码响应块
                                chunk_str = chunk.decode('utf-8')
                                
                                # 处理SSE格式的数据
                                for line in chunk_str.splitlines():
                                    line = line.strip()
                                    if line.startswith('data: '):
                                        data_part = line[6:]
                                        # 检查是否为结束标记
                                        if data_part == '[DONE]':
                                            continue
                                        
                                        try:
                                            # 解析JSON数据
                                            data = json.loads(data_part)
                                            
                                            # 获取内容（根据实际返回格式调整）
                                            content = ""
                                            if 'content' in data:
                                                content = data['content']
                                            elif 'choices' in data and isinstance(data['choices'], list) and data['choices']:
                                                delta = data['choices'][0].get('delta', {})
                                                content = delta.get('content', '')
                                            
                                            if content:
                                                accumulated_response += content
                                                
                                                # 构建完全匹配前端createAIChatStream预期的响应格式
                                                response_data = {
                                                    "content": content,
                                                    "finished": False,
                                                    "chat_id": chat_id,
                                                    "account_no": account_no
                                                }
                                                
                                                yield f"data: {json.dumps(response_data)}\n\n"
                                        except json.JSONDecodeError as e:
                                            pass
                # 发送完成信号 - 确保格式与前端createAIChatStream完全匹配
                final_response = {
                    "content": "",
                    "finished": True,
                    "chat_id": chat_id,
                    "account_no": account_no,
                    "status": "completed",
                    "total_content": accumulated_response
                }
                
                yield f"data: {json.dumps(final_response)}\n\n"
                
                # 记录请求完成信息
                duration = time.time() - start_time
                word_count = len(accumulated_response)

                
                # 流完成后保存聊天记录
                if accumulated_response:
                    try:
                        # 使用ChatService保存聊天记录，与非流式接口保持一致
                        save_ok = await chat_service.save_chat_message(
                            account_no=account_no,
                            user_msg=request.message,
                            assistant_msg=accumulated_response
                        )
                        if save_ok:
                            # 异步生成对话摘要，与非流式接口保持一致
                            import asyncio
                            asyncio.create_task(chat_service.generate_summary(account_no=account_no))
                        else:
                            pass
                    except Exception as save_error:

                        save_ok = False
            except httpx.RequestError as e:
                # 处理请求错误
                error_data = json.dumps({
                    "error": f"请求MaxKB服务失败: {str(e)}",
                    "chat_id": chat_id,
                    "account_no": account_no,
                    "status": "error"
                })
                yield f"data: {error_data}\n\n"
            except Exception as e:
                # 处理其他异常
                error_data = json.dumps({
                    "error": f"流式处理失败: {str(e)}",
                    "chat_id": chat_id,
                    "account_no": account_no,
                    "status": "error"
                })
                yield f"data: {error_data}\n\n"
            finally:
                if not save_ok and accumulated_response:
                    pass
        # 返回流式响应，确保设置正确的响应头
        return StreamingResponse(
            stream_generator(),
            media_type="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive"
            }
        )
        
    except Exception as e:
        # 捕获并处理全局异常
        async def global_error_generator():
            account_no_value = account_no if 'account_no' in locals() else ""
            error_data = json.dumps({
                "error": f"处理请求时发生错误: {str(e)}",
                "status": "error",
                "account_no": account_no_value
            })
            yield f"data: {error_data}\n\n"
        
        return StreamingResponse(
            global_error_generator(),
            media_type="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive"
            },
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


# 健康检查接口 - 更新以检查MAXKB_Chat_ID
class HealthResponse(BaseModel):
    status: str
    service: str = "maxkb"
    version: str = "1.0.0"
    message: Optional[str] = None
    chat_id: Optional[str] = None

@router.get("/health", response_model=HealthResponse)
async def maxkb_health_check() -> Dict[str, Any]:
    """
    MaxKB服务健康检查接口
    检查API URL、API Key和Chat ID配置
    
    Returns:
        服务状态信息
    """
    try:
        # 检查配置完整性
        if not settings.MAXKB_API_URL:
            return {
                "status": "unhealthy",
                "message": "MaxKB API URL未配置",
                "service": "maxkb",
                "version": "1.0.0",
                "chat_id": settings.MAXKB_Chat_ID
            }
        
        if not settings.MAXKB_API_KEY:
            return {
                "status": "unhealthy",
                "message": "MaxKB API Key未配置",
                "service": "maxkb",
                "version": "1.0.0",
                "chat_id": settings.MAXKB_Chat_ID
            }
        
        if not settings.MAXKB_Chat_ID:
            return {
                "status": "unhealthy",
                "message": "MaxKB对话ID未配置",
                "service": "maxkb",
                "version": "1.0.0",
                "chat_id": None
            }
        
        # 使用正确初始化的maxkb_agent进行健康检查
        try:
            profile = await maxkb_agent.get_application_profile()
            if "error" in profile:
                return {
                    "status": "degraded",
                    "message": f"无法连接到MaxKB服务: {profile.get('error', '未知错误')}",
                    "service": "maxkb",
                    "version": "1.0.0",
                    "chat_id": settings.MAXKB_Chat_ID
                }
            
            return {
                "status": "healthy",
                "message": "MaxKB服务连接正常",
                "service": "maxkb",
                "version": "1.0.0",
                "chat_id": settings.MAXKB_Chat_ID
            }
        except Exception as conn_error:
            return {
                "status": "degraded",
                "message": f"连接MaxKB服务时出错: {str(conn_error)}",
                "service": "maxkb",
                "version": "1.0.0",
                "chat_id": settings.MAXKB_Chat_ID
            }
    
    except Exception as e:
        return {
            "status": "unhealthy",
            "message": f"健康检查失败: {str(e)}",
            "service": "maxkb",
            "version": "1.0.0",
            "chat_id": settings.MAXKB_Chat_ID
        }

# 聊天记录查询窗口接口
@router.post("/chat/history", response_model=dict)
async def get_chat_history(request: ChatHistoryRequest, current_user: Dict[str, Any] = Depends(get_current_user)):
    """
    获取指定账号的聊天历史记录
    
    Args:
        request: 包含account_no、limit和offset参数的请求
        
    Returns:
        包含聊天历史记录和元数据的响应
    """
    try:
        # 使用ChatService获取聊天历史
        account_no = current_user.get("accountNo", "")
        history = await chat_service.get_chat_history(account_no=account_no)
        
        # Apply pagination in the router
        if request.offset < len(history):
            history = history[request.offset:request.offset + request.limit]
        
        # 格式化响应数据
        formatted_history = []
        for message in history:
            # We don't have a chat_id in the message structure, so set it to empty or use a default
            formatted_history.append(ChatHistoryItem(
                role=message.get("role", ""),
                content=message.get("content", ""),
                timestamp=message.get("timestamp", ""),
                chat_id=""  # Empty or default chat_id
            ))
        
        # 按时间戳排序
        formatted_history.sort(key=lambda x: x.timestamp, reverse=True)
        
        return {
            "success": True,
            "message": "获取聊天历史成功",
            "data": {
                "account_no": account_no,
                "total": len(formatted_history),
                "limit": request.limit,
                "offset": request.offset,
                "history": formatted_history
            }
        }
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        account_no = current_user.get("accountNo", "")
        logger.error(f"获取聊天历史失败: {str(e)}, account_no={account_no}")
        return {
            "success": False,
            "message": f"获取聊天历史失败: {str(e)}",
            "data": {
                "account_no": current_user.get("accountNo", "")
            }
        }

# 清空聊天历史接口
class ClearChatHistoryRequest(BaseModel):
    chat_id: Optional[str] = Field(None, description="要清空的对话ID，如果为None则清空所有")

@router.delete("/chat/history/clear", response_model=dict)
async def clear_chat_history(request: ClearChatHistoryRequest, current_user: Dict[str, Any] = Depends(get_current_user)):
    """
    清空指定账号的聊天历史记录
    
    Args:
        request: 包含可选的chat_id参数
        
    Returns:
        操作结果响应
    """
    try:
        account_no = current_user.get("accountNo", "")
        
        # 调用ChatService清空聊天历史（移除chat_id参数，因为service层已不支持）
        success = await chat_service.clear_chat_history(
            account_no=account_no
        )
        
        if success:
            return {
                "success": True,
                "message": "清空聊天历史成功",
                "data": {
                    "account_no": account_no,
                    "chat_id": request.chat_id
                }
            }
        else:
            return {
                "success": False,
                "message": "清空聊天历史失败",
                "data": {
                    "account_no": account_no,
                    "chat_id": request.chat_id
                }
            }
    except Exception as e:
        import logging
        logger = logging.getLogger(__name__)
        account_no = current_user.get("accountNo", "")
        logger.error(f"清空聊天历史失败: {str(e)}, account_no={account_no}")
        return {
            "success": False,
            "message": f"清空聊天历史失败: {str(e)}",
            "data": {
                "account_no": account_no,
                "chat_id": request.chat_id
            }
        }